package com.tools.commons.response;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;

import java.util.Locale;

/**
 * @author wangminggen
 */
@Component
@Slf4j
public class R implements ApplicationContextAware {
    /**
     * @param code code
     * @param <T>  泛型
     * @return 操作失败，返回自定义的失败code信息
     */
    public static <T> Result<T> fail(ResponseCode code) {
        return fail(code, (String) null);
    }

    /**
     * @param code code
     * @param args message可变参数
     * @param <T>  泛型
     * @return 操作失败，返回自定义的失败code信息，并填充message 可变字段
     */
    public static <T> Result<T> fail(ResponseCode code, String... args) {
        return fail(null, code, args);
    }

    /**
     * @param code code
     * @param args message可变参数
     * @param <T>  泛型
     * @return 操作失败，返回自定义的失败code信息，并填充message 可变字段
     */
    public static <T> Result<T> fail(T errData, ResponseCode code, String... args) {
        return result(errData, code, args);
    }

    /**
     * @param <T> 泛型
     * @return 操作成功, 返回一个不包含数据的成功消息
     */
    public static <T> Result<T> ok() {
        return ok(null);
    }

    /**
     * @param data 数据
     * @param <T>  泛型
     * @return 返回一个包含数据的成功消息
     */
    public static <T> Result<T> ok(T data) {
        return result(data, ResponseCode.SUCCESS, (String) null);
    }

    /**
     * @param data 数据
     * @param code code
     * @param args message可变参数
     * @param <T>  泛型
     * @return 返回一个包含数据的消息，且message为动态的
     */
    private static <T> Result<T> result(T data, ResponseCode code, String... args) {
        return Result.newInstance(data, code.getCode(), makeMessage(code, args));
    }

    public static String makeMessage(ResponseCode code, String[] args) {
        String message = code.getDefaultMsgTemplate();
        if (code.getI18nKey() != null && messagesource != null) {
            Locale locale = LocaleContextHolder.getLocale();
            message = messagesource.getMessage(code.getI18nKey(), args, locale);
            if (log.isDebugEnabled()) {
                log.info("i18n,lang => {}，key => {}, msg => {}", locale, code.getI18nKey(), message);
            }
        } else {
            String key = LEFT + 0 + RIGHT;
            if (args != null && message.contains(key)) {
                for (int i = 0; i < args.length && message.contains(key) && args[i] != null; i++, key = LEFT + i + RIGHT) {
                    message = message.replace(key, args[i]);
                }
            }
            if (log.isDebugEnabled()) {
                log.info("final msg => {}", message);
            }
        }
        return message;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        messagesource = applicationContext.getBean(MessageSource.class);
    }

    private static final String LEFT = "{";
    private static final String RIGHT = "}";
    private static MessageSource messagesource;
}
